package Classes.GameUtils// ActionScript file
{
	import Classes.Interfaces.I_Bar;
	import Classes.Interfaces.I_FindingTarget;
	
	import flash.geom.Point;

	/**
	 *障碍寻径逻辑类 
	 * @author jamesge
	 * 
	 */	
	public class GU_BarPathFinding
	{
		private static var _findingTarget:I_FindingTarget;/*寻径目标*/
		private static var _point_l:Point;/*寻径终点*/
		private static var _findingAry:Array;/*搜寻策略数组*/
		private static var _arriveAry:Array;/*已到达的策略数组*/
		public static var _actTarget:I_Bar;
		public static function getPolicyPointsAry(point_f:Point,point_l:Point,findingTarget:I_FindingTarget,actTarget:I_Bar=null):Array
		{
			GU_BarPathFinding.findingTarget=findingTarget;
			GU_BarPathFinding.point_l=point_l;
			GU_BarPathFinding.findingAry=new Array;
			GU_BarPathFinding.arriveAry=new Array;
			GU_BarPathFinding._actTarget=actTarget;
			var firstPolicy:FindingPolicy=new FindingPolicy(null,point_f);
			GU_BarPathFinding.findingAry.push(firstPolicy);
			var lastPolicy:FindingPolicy=checkPolicys();
			var returnAry:Array=new Array;
			var targetPoint:Point=point_l;
			
			while(lastPolicy)
			{
				returnAry.unshift(targetPoint);
				targetPoint=lastPolicy.targetPoint;
				lastPolicy=lastPolicy.parentPolicy;
			}
			return returnAry;
		}
		
		/**
		 *检测所有策略，并返回最终寻径策略，返回空表示无法到达 
		 * @return 
		 * 
		 */		
		public static function checkPolicys():FindingPolicy
		{
			while(GU_BarPathFinding.findingAry.length)
			{
				var checkPolicy:FindingPolicy=GU_BarPathFinding.findingAry.shift();
				if(checkPolicy.checkArrive())
				{
					if(checkPolicy.checkCome())
					{
						return checkPolicy;
					}
					for(var i:int=0;i<GU_BarPathFinding.findingAry.length;i++)
					{
						var waitCheckPolicy:FindingPolicy=GU_BarPathFinding.findingAry[i];
						
						/*删除那些到达目标与该到达点相同的策略（因为已经通过最短路径到达，策略失效）*/
						if(waitCheckPolicy.targetPoint.equals(checkPolicy.targetPoint))
						{
							GU_BarPathFinding.findingAry.splice(i,1);
							i--;
						}
					}
					GU_BarPathFinding.arriveAry.push(checkPolicy.targetPoint);
				}
				GU_BarPathFinding.findingAry.sortOn("findingPrice",Array.NUMERIC);
			}
			return null;
		}
	
		public static function crossBar(policy:FindingPolicy,bar:I_Bar):void
		{
			/*检测障碍是否已经存在于目标策略的已穿越障碍表中,是的话就不再添加*/
			for each(var checkBar:I_Bar in policy.crossBarsAry)
			{
				if(checkBar==bar)
				{
					return;
				}
			}
			
			/*获取目标障碍的顶点数组*/
			var vertexsAry:Array=bar.getVertexsAry();
			
			/*建立从策略的目标点到障碍顶点的新策略（如果顶点在已到达列表中，或者顶点就是策略自身出发点则不需要添加）*/
			checkNext:
			for(var i:int=0;i<vertexsAry.length;i++)
			{
				var targetPoint:Point=vertexsAry[i];
				for(var j:int=0;j<GU_BarPathFinding.arriveAry.length;j++)
				{
					var arrivePoint:Point=GU_BarPathFinding.arriveAry[j];
					if(targetPoint.equals(arrivePoint))
					{
						continue checkNext;
					}
				}
				if(!policy.targetPoint.equals(targetPoint))
				{
					var newPolicy:FindingPolicy=new FindingPolicy(policy,targetPoint);
					findingAry.push(newPolicy);
				}
			}
			
			/*将该障碍加入策略的已穿越障碍表*/
			policy.crossBarsAry.push(bar);
			
			/*如果该策略存在父策略，还需要为该策略的父策略增加穿越障碍的新策略*/
			if(policy.parentPolicy)crossBar(policy.parentPolicy,bar);
		}

		/*getter & setter*/
		public static function get findingTarget():I_FindingTarget
		{
			return _findingTarget;
		}

		public static function set findingTarget(value:I_FindingTarget):void
		{
			_findingTarget = value;
		}

		public static function get point_l():Point
		{
			return _point_l;
		}

		public static function set point_l(value:Point):void
		{
			_point_l = value;
		}

		public static function get findingAry():Array
		{
			return _findingAry;
		}

		public static function set findingAry(value:Array):void
		{
			_findingAry = value;
		}

		public static function get arriveAry():Array
		{
			return _arriveAry;
		}

		public static function set arriveAry(value:Array):void
		{
			_arriveAry = value;
		}
	}
}

import Classes.GameUtils.GU_BarPathFinding;
import Classes.Interfaces.I_Bar;
import Classes.Interfaces.I_FindingTarget;

import flash.geom.Point;

/**
 *寻径策略类 
 * @author jamesge
 * 
 */
class FindingPolicy
{
	private var _parentPolicy:FindingPolicy;/*父策略*/
	private var _targetPoint:Point;/*目标点*/
	private var _crossBarsAry:Array;/*已经穿越的障碍表*/
	private var _arrivePrice:Number=0;/*实际到达代价*/
	
	public function FindingPolicy(parentPolicy:FindingPolicy,targetPoint:Point):void
	{
		this._parentPolicy=parentPolicy;
		this._targetPoint=targetPoint;
		this._crossBarsAry=new Array;
	}
	
	/**
	 *检测是否能顺利到达该策略的目标
	 * @return 
	 * 
	 */	
	public function checkArrive():Boolean
	{
		if(!this.parentPolicy)return true;
		var bar:I_Bar=GU_BarPathFinding.findingTarget.getFirstBarBetweenTwoPoints(this.parentPolicy.targetPoint,this.targetPoint,GU_BarPathFinding._actTarget);
		
		/*如果有障碍的话，为父策略点增加穿越该障碍的策略*/
		if(bar)
		{
			GU_BarPathFinding.crossBar(this.parentPolicy,bar);
			return false;
		}
		else
		{
			if(this.parentPolicy)
			{
				var estimateArrivePrice:Number=GU_BarPathFinding.findingTarget.getFindingPriceBetweenTwoPoints(this.parentPolicy.targetPoint,this.targetPoint);
				this.arrivePrice=estimateArrivePrice+this.parentPolicy.arrivePrice;
			}
			return true;
		}
		
	}
	
	/**
	 *检测由该策略的目标是否能顺利到达终点 
	 * @return 
	 * 
	 */	
	public function checkCome():Boolean
	{
		var bar:I_Bar=GU_BarPathFinding.findingTarget.getFirstBarBetweenTwoPoints(this.targetPoint,GU_BarPathFinding.point_l,GU_BarPathFinding._actTarget);
		
		/*如果有障碍的话，为自身增加穿越该障碍的策略*/
		if(bar)
		{
			GU_BarPathFinding.crossBar(this,bar);
			return false;
		}
		else
		{
			return true;
		}
	}

	
	/*getter & setter*/
	public function get parentPolicy():FindingPolicy
	{
		return _parentPolicy;
	}

	public function get targetPoint():Point
	{
		return _targetPoint;
	}

	public function get crossBarsAry():Array
	{
		return _crossBarsAry;
	}
	
	public function get arrivePrice():Number
	{
		return _arrivePrice;
	}
	
	public function set arrivePrice(value:Number):void
	{
		_arrivePrice = value;
	}
	
	/**
	 *获取该策略的寻径代价 
	 * @return 
	 * 
	 */	
	public function get findingPrice():Number
	{
		var arriveTotalPrice:Number=0;
		if(this.parentPolicy)
		{
			var parentPrice:Number=this.parentPolicy.arrivePrice;
			var estimateArrivePrice:Number=GU_BarPathFinding.findingTarget.getFindingPriceBetweenTwoPoints(this.parentPolicy.targetPoint,this.targetPoint);
			arriveTotalPrice=parentPrice+estimateArrivePrice;
		}
		var comePrice:Number=GU_BarPathFinding.findingTarget.getFindingPriceBetweenTwoPoints(this.targetPoint,GU_BarPathFinding.point_l);
		return arriveTotalPrice+comePrice;
	}
}